﻿using System;
using System.Collections.Generic;
using System.Text;

namespace ZeBobo5.LibraryHelper.Orm
{
    internal class OrmQueryFactory
    {
        public static string GetSelectQuery<T>(T data) where T : IOrmDataElementBase
        {
            return string.Concat("SELECT * FROM {0} ", typeof (T).Name);
        }

        public static string GetInsertQuery<T>(T data) where T : OrmDataElementBase<T>
        {
            return GetInsertQuery(data, false);
        }

        public static string GetInsertQuery<T>(T data, bool allowInsertNULL) where T : OrmDataElementBase<T>
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("INSERT INTO {0} ", typeof (T).Name);
            sb.Append(SpecificPart.GetInsertFields(data));
            sb.Append(" VALUES ");
            sb.Append(SpecificPart.GetInsertValues(data));
            return sb.ToString();
        }

        public static string GetUpdateQuery<T>(T data) where T : OrmDataElementBase<T>
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("UPDATE {0} SET ", typeof (T).Name);
            sb.Append(SpecificPart.GetUpdateSetString(data));
            sb.Append(" WHERE ");
            sb.Append(SpecificPart.GetWhereConditionString(data));
            return sb.ToString();
        }

        public static string GetDeleteQuery<T>(T data) where T : OrmDataElementBase<T>
        {
            return string.Format("DELETE FROM {0} WHERE {1}", typeof (T).Name, SpecificPart.GetWhereConditionString(data));
        }

        #region Nested type: SpecificPart

        public class SpecificPart
        {
            public static string GetWhereConditionString<T>(T data)
                where T : OrmDataElementBase<T>
            {
                OrmWhereFactory where = null;
                foreach (KeyValuePair<OrmFieldBase<T>, Type> valuePair in data._colFields)
                {
                    if (where == null)
                    {
                        switch (valuePair.Key.ValuesType().Name.ToLower())
                        {
                            case "string":
                                where = OrmWhereFactory.Comparators<T>.EqualityString(valuePair.Key, valuePair.Key.GetValues(data)._originalValue.ToString());
                                break;
                            default:
                                where = OrmWhereFactory.Comparators<T>.Equality(valuePair.Key, valuePair.Key.GetValues(data)._originalValue);
                                break;
                        }
                    }
                    else switch (valuePair.Key.ValuesType().Name.ToLower())
                    {
                        case "string":
                            where = where.And(OrmWhereFactory.Comparators<T>.EqualityString(valuePair.Key, valuePair.Key.GetValues(data)._originalValue.ToString()));
                            break;
                        default:
                            where = where.And(OrmWhereFactory.Comparators<T>.Equality(valuePair.Key, valuePair.Key.GetValues(data)._originalValue));
                            break;
                    }
                }
                if (where != null)
                {
                    return where.SqlText;
                }
                return "";
            }

            public static string GetInsertFields<T>(T data) where T : OrmDataElementBase<T>
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("(");

                foreach (KeyValuePair<OrmFieldBase<T>, Type> valuePair in data._colFields)
                {
                    sb.Append(valuePair.Key.FieldName);
                    sb.Append(", ");
                }
                sb.Remove(sb.Length - 2, 2);
                sb.Append(")");
                return sb.ToString();
            }

            public static string GetInsertValues<T>(T data) where T : OrmDataElementBase<T>
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("(");

                foreach (KeyValuePair<OrmFieldBase<T>, Type> valuePair in data._colFields)
                {
                    if (valuePair.Key.ValuesType().Name.ToLower() == "string")
                    {
                        sb.AppendFormat("'{0}'", valuePair.Key.GetValues(data)._currentValue);
                    }
                    else
                    {
                        sb.Append(valuePair.Key.GetValues(data)._currentValue);
                    }
                    sb.Append(", ");
                }
                sb.Remove(sb.Length - 2, 2);
                sb.Append(")");
                return sb.ToString();
            }

            public static string GetUpdateSetString<T>(T data) where T : OrmDataElementBase<T>
            {
                StringBuilder sb = new StringBuilder();

                foreach (KeyValuePair<OrmFieldBase<T>, Type> valuePair in data._colFields)
                {
                    if (valuePair.Key.ValuesType().Name.ToLower() == "string")
                    {
                        sb.AppendFormat("{0}='{1}'", valuePair.Key.FieldName, valuePair.Key.GetValues(data)._currentValue);
                    }
                    else
                    {
                        sb.AppendFormat("{0}={1}", valuePair.Key.FieldName, valuePair.Key.GetValues(data)._currentValue);
                    }
                    sb.Append(", ");
                }
                sb.Remove(sb.Length - 2, 2);
                return sb.ToString();
            }
        }

        #endregion
    }
}